package com.zgc.util;

import com.fx.spring.util.SpringContextUtil;
import com.zgc.view.common.AlertCtrl;
import com.zgc.view.common.PopupCtrl;
import com.zgc.zkinfo.ZkConnectionInfo;
import com.zgc.zkinfo.ZkNodeInfo;
import javafx.application.Platform;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CreateBuilder;
import org.apache.curator.framework.api.CreateBuilderMain;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.EphemeralType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class CuratorZkUtil {
    private static final Logger logger = LoggerFactory.getLogger(CuratorZkUtil.class);

    private static final PopupCtrl popupCtrl = SpringContextUtil.getBean(PopupCtrl.class);


    /**
     * 是否连接
     *
     * @param curatorZkClient CuratorFramework
     * @return boolean
     */
    public static boolean isConnect(CuratorFramework curatorZkClient) {
        if (Objects.isNull(curatorZkClient)) {
            return false;
        }


        return curatorZkClient.getZookeeperClient().isConnected();
    }

    /**
     * 获取主机地址
     *
     * @param curatorZkClient CuratorFramework
     * @return 主机地址
     */
    public static String getHost(CuratorFramework curatorZkClient) {
        Asserts.assertsCuratorNotNull(curatorZkClient);
        return curatorZkClient.getZookeeperClient().getCurrentConnectionString();
    }

    /**
     * 获取连接超时时间
     *
     * @param curatorZkClient CuratorFramework
     * @return 连接超时时间（单位：毫秒）
     */
    public static Integer getConnectTimeoutMs(CuratorFramework curatorZkClient) {
        Asserts.assertsCuratorNotNull(curatorZkClient);
        return curatorZkClient.getZookeeperClient().getConnectionTimeoutMs();
    }

    /**
     * 获取会话超时时间
     *
     * @param curatorZkClient CuratorFramework
     * @return 会话超时时间（单位：毫秒）
     */
    public static Integer getSessionTimeoutMs(CuratorFramework curatorZkClient) {
        Asserts.assertsCuratorNotNull(curatorZkClient);
        return curatorZkClient.getZookeeperClient().getLastNegotiatedSessionTimeoutMs();
    }

    /**
     * 获取zookeeper
     *
     * @param curatorZkClient CuratorFramework
     * @return ZooKeeper
     */
    public static ZooKeeper getZooKeeper(CuratorFramework curatorZkClient) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return curatorZkClient.getZookeeperClient().getZooKeeper();
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取zookeeper异常", e);
        }
        return null;
    }

    public static void asynClose(CuratorFramework curatorZkClient, ZkConnectionInfo zkConnectionInfo) {
        Asserts.assertsCuratorNotNull(curatorZkClient);
        Platform.runLater(() -> {
            curatorZkClient.close();
            zkConnectionInfo.setConnected(isConnect(curatorZkClient));
        });
    }

    /**
     * 判断系节点是否存在
     *
     * @param curatorZkClient CuratorFramework
     * @param path            路径
     * @return true 节点存在，false 节点不存在
     */
    public static boolean exit(CuratorFramework curatorZkClient, String path) {
        try {
            return curatorZkClient.checkExists().forPath(path) != null;
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("检查[{}]节点存在异常", path, e);
        }
        return false;
    }

    /**
     * 获取指定节点的子节点列表
     *
     * @param curatorZkClient CuratorFramework
     * @param path            节点路径
     * @return 子节点列表
     */
    public static List<String> getChildren(CuratorFramework curatorZkClient, String path) {
        List<String> pathList;
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            pathList = curatorZkClient.getChildren().forPath(path);
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取[{}]节点列表异常", path, e);
            pathList = new ArrayList<>();
        }
        return pathList;
    }

    /**
     * 获取指定节点的子节点列表
     *
     * @param curatorZkClient CuratorFramework
     * @param zkNodeInfo      ZkNodeInfo
     * @return 子节点列表
     */
    public static List<String> getChildren(CuratorFramework curatorZkClient, ZkNodeInfo zkNodeInfo) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return curatorZkClient.getChildren().storingStatIn(zkNodeInfo.getStat()).forPath(zkNodeInfo.getPath());
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取[{}]节点列表异常", zkNodeInfo.getPath(), e);
            return Collections.emptyList();
        }
    }

    /**
     * 获取指定节点的数据
     *
     * @param curatorZkClient CuratorFramework
     * @param path            节点路径
     * @return 数据
     */
    public static String getData(CuratorFramework curatorZkClient, String path) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return new String(curatorZkClient.getData().forPath(path));
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取[{}]节点数据异常", path, e);
        }
        return null;
    }

    /**
     * 更新指定节点的数据
     *
     * @param curatorZkClient CuratorFramework
     * @param path            节点路径
     * @param data            数据
     * @return Stat
     */
    public static Stat setData(CuratorFramework curatorZkClient, String path, byte[] data) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return curatorZkClient.setData().forPath(path, data);
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("更新[{}]节点数据异常", path, e);
        }
        return null;
    }

    /**
     * 获取指定节点的数据
     *
     * @param curatorZkClient CuratorFramework
     * @param zkNodeInfo      ZkNodeInfo
     */
    public static void getData(CuratorFramework curatorZkClient, ZkNodeInfo zkNodeInfo) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            zkNodeInfo.setData(curatorZkClient.getData().storingStatIn(zkNodeInfo.getStat()).forPath(zkNodeInfo.getPath()));
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取[{}]节点数据异常", zkNodeInfo.getPath(), e);
        }
    }

    /**
     * 获取ACL权限列表
     *
     * @param curatorZkClient CuratorFramework
     * @param path            当前路径
     * @return ACL权限列表
     */
    public static List<ACL> getACL(CuratorFramework curatorZkClient, String path) {
        List<ACL> aclList;
        try {
            aclList = curatorZkClient.getACL().forPath(path);
            Asserts.assertsCuratorNotNull(curatorZkClient);
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取[{}]节点ACL信息异常", path, e);
            aclList = new ArrayList<>();
        }
        return aclList;
    }

    /**
     * 获取ACL权限列表
     *
     * @param curatorZkClient CuratorFramework
     * @param zkNodeInfo      ZkNodeInfo
     */
    public static void getACL(CuratorFramework curatorZkClient, ZkNodeInfo zkNodeInfo) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            zkNodeInfo.setAcl(curatorZkClient.getACL().forPath(zkNodeInfo.getPath()));
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("获取[{}]节点ACL信息异常", zkNodeInfo.getPath(), e);
        }
    }

    /**
     * 创建节点
     *
     * @param curatorZkClient CuratorFramework
     * @param path            路径
     * @param mode            节点类型
     * @param data            数据
     */
    public static String create(CuratorFramework curatorZkClient, String path, CreateMode mode, byte[] data) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return curatorZkClient.create().creatingParentsIfNeeded().withMode(mode).forPath(path, data);
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("创建[{}]节点异常", path, e);
        }
        return null;
    }

    /**
     * 创建节点
     *
     * @param curatorZkClient CuratorFramework
     * @param path            路径
     * @param mode            节点类型
     * @param data            数据
     * @param ttl             生命周期
     */
    public static String create(CuratorFramework curatorZkClient, String path, CreateMode mode, byte[] data, Long ttl) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return curatorZkClient.create().withTtl(ttl).creatingParentsIfNeeded().withMode(mode).forPath(path, data);
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("创建[{}]节点异常", path, e);
        }
        return null;
    }


    /**
     * 创建节点
     *
     * @param curatorZkClient CuratorFramework
     * @param zkNodeInfo      ZkNodeInfo
     */
    public static String create(CuratorFramework curatorZkClient, ZkNodeInfo zkNodeInfo, CreateMode mode) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            return curatorZkClient.create().creatingParentsIfNeeded().withMode(mode).forPath(zkNodeInfo.getPath(), zkNodeInfo.getData());
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("创建[{}]节点异常", zkNodeInfo.getStat(), e);
        }
        return null;
    }

    /**
     * 删除节点，包含子节点
     *
     * @param curatorZkClient CuratorFramework
     * @param path            路径
     */
    public static boolean delete(CuratorFramework curatorZkClient, String path) {
        try {
            Asserts.assertsCuratorNotNull(curatorZkClient);
            curatorZkClient.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
            return true;
        } catch (Exception e) {
            popupCtrl.enqueueRoot("", e.getMessage());
            logger.error("删除[{}]节点异常", path, e);
        }
        return false;
    }
}
